#define FACTOR 1


/*! \file Pattern.hpp
  \brief Une classe qui simule un pattern d'allocation, 
  il faudera lui fournir une distribution pour qu'elle fonctionne. 
*/
#ifndef __PATTERN_HPP__
#define __PATTERN_HPP__

#include <iostream>
#include <cstdlib>

#include "IAllocDistribution.hpp"
#include "FactoryDistribution.hpp"
#include "DefaultAllocDistribution.hpp"
#include "SourceBinaire.hpp"
//#include "DumperFactory.h"


//using namespace std;

/**
 * \class Pattern 
 * \brief Un pattern (au sens motif (sequence d'allocation liberation) et non design pattern) d'allocation memoire
 */
class Pattern
{
private:


  /**
   *\brief Dumper utilise pour instrumenter ce pattern
   */
  //IDumper* dumper;
  
  
  /**
   *\brief Source binaire utilisée pour décider d'ecrire dans un bloc
   */
  SourceBinaire* sourceBinaire;
  
  /**
   *\brief Taille du pattern d'allocation; ie le nombre de malloc,new 
   */
  long int PatternTaille;
  /**
   * \brief Sequence de pointeurs référençant la mémoire allouée lors du flot 
   * d'execution
   */
  char **patternMemory;
  /**
   *\brief Distribution en taille des blocs alloués
   *Pour ne pas perturber le comportement du programme, 
   *il vaut mieux stocker cette chose ailleurs que dans le tas du processus courant
   */
  int  * taillesBlocs ;
  
  
  /******************/
  bool * allocated;
  bool * freed;
  /*****************/
  
  long int steps;
  long int freeds;
  /**
   * \brief La fonction de distribution utilisée pour faire les simulations
   * */
  IAllocDistribution * distributeur; 
  /**
   *\brief Distribution de la durée de vie des blocs
   *en terme d'alloc event (t)
   *@ie:   
   *   b1=new     (t=1)
   *   b2=new     (t=2)
   *   b3=new     (t=3)
   *   b4=new     (t=4)
   *   delete b1  (t=5)
   *   delete b4  (t=6)
   *   b5=new     (t=7)
   *   b6=new     (t=8)
   *   delete b3  (t=9)
   *   delete b2  (t=10)
   *   delete b5  (t=11)
   *   delete b6  (t=12)
   *   Avec une telle représentation du temps on obtient le tableau suivant des durées de vie
   *   -----------------------------------------------------
   *   bloc      |   b1  |  b2  |  b3  |  b4  |  b5  |  b6  |
   *   ------------------------------------------------------
   *   naissance |   1   |  2   |  3   |  4   |  7   |  8   |
   *   ------------------------------------------------------
   *   mort      |   5   |  10  |  9   |  6   |  11  | 12   |
   *   ------------------------------------------------------
   *   durée vie |   4   |  8   |  6   |  2   |  4   | 4    |
   *   ------------------------------------------------------
   */
  unsigned int * dureesBlocs;
  
  
public:
  /**
   *\brief Constructeur qui prends le nombre de bloc et la fonction de distribution
   */
  Pattern(int nbBlocs, IAllocDistribution* distributeur,SourceBinaire* sb,bool scale=true)
  {
    int factor;
    //std::cout << "Taille: "<< nbBlocs<<std::endl;
    this->PatternTaille = nbBlocs;
    this->steps = 0;
    this->freed = 0;
    this->distributeur= distributeur;
    this->taillesBlocs =new int  [nbBlocs];
    //this->etatsBlocs   =new bool [nbBlocs];		
    this->allocated   =new bool [nbBlocs];	
    this->freed       =new bool [nbBlocs];		
    this->dureesBlocs  =new unsigned int  [nbBlocs];
    this->patternMemory=new char* [nbBlocs];
    this->sourceBinaire=sb;
    
    //Cette ligne est par défaut pour l'instant
    //this->dumper=DumperFactory::getDumperStatus();
    //this->dumper->printHeader();
    
    
    /*Initialisation des blocs de mémoire*/
    for(int i = 0 ; i< this->PatternTaille; i++){
      patternMemory[i]= NULL;
      
      /************************/
      this->allocated[i]=false;
      this->freed[i]=false;
      this->freeds=0;
      /*Cette ligne peut être abstraite*/
      this->distributeur->genererBloc(i);
      
      dureesBlocs[i] = distributeur->getBlocLife(i); 
      if(!scale)
	factor = 1;
      else
	factor = FACTOR;
      
      taillesBlocs[i]= distributeur->getBlocSize(i)*FACTOR;
      
      assert(taillesBlocs[i] >= 0);
      assert(dureesBlocs [i] >= 0);
    }
  }
  
  /**
   *\brief Destructeur 
   */
  ~Pattern()
  {
    std::cout << "Fin"<<std::endl;
    delete taillesBlocs;
    //delete etatsBlocs;
    delete dureesBlocs;
    //delete patternMemory;
  }
  
  
  /**
   *\brief Boucle d'allocation
   */
  void lancerSimulation();
  
  /**
   *\brief Prend une mesure
   */
  void dumpMeasures();
private:
  /**
   *\brief Ecriture du bloc id
   */
  void writeBlocAt(unsigned int id,size_t len); 
};

#endif
